/*LICENSE_BEGIN
 * ******************************************************************
 * All original parts of SoccerScope2003 have copyright (2003) by
 * Team YowAI, represented by Mr. Shuhei Shiota
 * The Department of Creative Informatics
 * The Graduate School of Information Science and Technology
 * The University of Tokyo
 * 
 * Additional classes (except libraries in /lib) were developed by 
 * the Dainamite Robocup-Team of the DAI-Labor, TU-Berlin 
 * (www.dai-labor.de)
 * 
 * Extended/new classes/packages are:
 *   soccerscope.analyzer.LogfileAnalyzer
 *   soccerscope.daistatistic.*
 *   soccerscope.daistatistic.charts.*
 *   soccerscope.daistatistic.tools.*
 *   soccerscope.db.*
 *   soccerscope.dialog.*
 *   soccerscope.model.PlayerWorldModel
 *   soccerscope.model.SimplePlayer
 *   soccerscope.net.AgentConnector
 *   soccerscope.training.*
 *   soccerscope.training.conditions.*
 * ******************************************************************
LICENSE_END*/
package soccerscope.view.layer;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Arrays;

import soccerscope.model.Ball;
import soccerscope.model.Player;
import soccerscope.model.SoccerObject;
import soccerscope.model.SoccerObjectID;
import soccerscope.model.Team;
import soccerscope.model.WorldModel;
import soccerscope.training.ObjectTrainingModel;
import soccerscope.training.PlayerTrainingModel;
import soccerscope.training.TrainingModel;
import soccerscope.training.ObjectTrainingModel.POSITION_TYPE;
import soccerscope.util.Color2;
import soccerscope.util.geom.Point2f;
import soccerscope.util.geom.Tuple2f;
import soccerscope.view.FieldPane;
import soccerscope.view.SoccerObjectSelectObserver;

public class TrainingModelLayer extends Layer implements
		SoccerObjectSelectObserver, SoccerObjectID {

	private boolean selected[] = new boolean[MAX_ID];

	public TrainingModelLayer(FieldPane fieldPane, boolean enable) {
		super(fieldPane, enable);
		Arrays.fill(this.selected, false);
	}

	@Override
	public String getLayerName() {
		return "TrainigModelLayer";
	}

	/**
	 * This method just stores the selected ID
	 */
	public void selectSoccerObject(int id, boolean flag) {
		if (id != MAX_ID)
			this.selected[id] = flag;
	}

	/**
	 * Here, the Players Trainings-Data is painted:
	 */
	@Override
	public void draw(Graphics g) {
		if (!this.enable)
			return;

		// ClientScene scene = fieldPane.getScene();
		TrainingModel tm = WorldModel.getInstance().trainModel;
		// System.out.println("DRAW-ME " + tm);
		if (tm == null)
			return;

		((Graphics2D) g).setComposite(AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 0.2f));

		// Draw all Players training-data
		Player player = null;
		for (int i = 0; i < BALL; i++) {
			if (!this.selected[i])
				continue;

			player = this.fieldPane.getScene().player[i];
			if (player == null)
				return;

			PlayerTrainingModel ptm = (PlayerTrainingModel) tm.objectTrainingModel[i];

			// draw the trainingsdata
			this.drawPositionModel(g, player, ptm);
			this.drawBodyAngleModel(g, ptm);
			this.drawSpeedModel(g, ptm);
			this.drawPositionMapping(g, ptm);
			this.drawOtherAttributes(g, ptm);

		}

		// draw all Ball training-data
		if (this.selected[BALL]) {
			Ball ball = this.fieldPane.getScene().ball;
			ObjectTrainingModel otm = tm.objectTrainingModel[BALL];

			this.drawPositionModel(g, ball, otm);
			this.drawSpeedModel(g, otm);
			this.drawPositionMapping(g, otm);
		}
		((Graphics2D) g).setComposite(AlphaComposite.getInstance(
				AlphaComposite.SRC_OVER, 1.0f));
	}

	/**
	 * This method visualizes the attributes: -active -roundView (and other)
	 * 
	 * @param g -
	 *            the graphic context
	 * @param ptm -
	 *            the training-model
	 */
	private void drawOtherAttributes(Graphics g, PlayerTrainingModel ptm) {
		String s = "";
		if (ptm.isActive())
			s += "A";
		if (ptm.isRoundView())
			s += "R";

		if (s.length() > 0) {
			((Graphics2D) g).setComposite(AlphaComposite.getInstance(
					AlphaComposite.SRC_OVER, 0.8f));
			Color old = g.getColor();
			g.setColor(Color2.white);
			Point2f pos = new Point2f();
			pos.x = ptm.getPosition().x + 0.5f;
			pos.y = ptm.getPosition().y + 0.5f;
			this.drawString(g, s, pos);
			g.setColor(old);
			((Graphics2D) g).setComposite(AlphaComposite.getInstance(
					AlphaComposite.SRC_OVER, 0.2f));
		}
	}

	/**
	 * This method draws a small cross to the field, when the mouse-position is
	 * over the trainingsButton - indicating the position which maps from the
	 * button to the field!
	 * 
	 * @param g -
	 *            graphic-context
	 * @param ptm -
	 *            the training-model
	 */
	private void drawPositionMapping(Graphics g, ObjectTrainingModel ptm) {
		if (ptm.getObservePoint() == null)
			return;
		Color old = g.getColor();
		g.setColor(Color2.black);
		this.drawString(g, "x", ptm.getObservePoint());
		g.setColor(old);
	}

	/**
	 * This method draws the position-model. If the model is FIXED, the position
	 * is the actual player himself, nothing has to be drawn. If the model is
	 * RECTANGULAR or CIRCULAR, the corresponding shape has to be drawn around
	 * the Player with an amount of transparency!
	 * 
	 * @param g -
	 *            the graphics-context
	 * @param ptm -
	 *            the trainings-model of the player
	 */
	private void drawPositionModel(Graphics g, SoccerObject object,
			ObjectTrainingModel otm) {
		if (otm.getType() == POSITION_TYPE.FIXED) {
			this.drawArrow(g, new Point2f(), otm.getPosition());
			return;
		}
		Color old = g.getColor();
		if (otm instanceof PlayerTrainingModel) {
			if (((Player) object).side == Team.LEFT_SIDE)
				g.setColor(Color2.yellow);
			else
				g.setColor(Color2.red);
		} else {
			g.setColor(Color2.white);
		}

		if (otm.getType() == POSITION_TYPE.RECTANGULAR) {
			Point2f pos = otm.getPosition();
			// the other way round in soccerscope:
			float ydiff = otm.getX_pos_diff();
			float xdiff = otm.getY_pos_diff();
			this.fillRect(g, new Point2f(pos.x - xdiff, pos.y - ydiff),
					new Tuple2f((2 * xdiff), (2 * ydiff)));
			// Point2f p = otm.generatePosition();
			// g.setColor(Color2.black);
			// this.fillOval(g, new Point2f(p.x - 1, p.y - 1),
			// new Tuple2f(2,(2)));

		} else if (otm.getType() == POSITION_TYPE.CIRCULAR) {

			Point2f pos = otm.getPosition();
			// the other way round in soccerscope
			float ydiff = otm.getX_pos_diff();
			float xdiff = otm.getY_pos_diff();

			this.fillOval(g, new Point2f(pos.x - xdiff, pos.y - ydiff),
					new Tuple2f((2 * xdiff), (2 * ydiff)));
			// Point2f p = otm.generatePosition();
			// g.setColor(Color2.black);
			// this.fillOval(g, new Point2f(p.x - 1, p.y - 1),
			// new Tuple2f(2,(2)));

		}
		g.setColor(old);
	}

	private void drawBodyAngleModel(Graphics g, PlayerTrainingModel ptm) {
		Color old = g.getColor();
		g.setColor(Color2.lightGreen);

		Point2f pos = ptm.getPosition();
		// the other way round in soccerscope
		float ydiff = 3;
		float xdiff = 3;
		float angle = -ptm.getBody_angle();
		float adiff = ptm.getBody_angle_diff();
		this.fillArc(g, new Point2f(pos.x - xdiff, pos.y - ydiff), new Tuple2f(
				(2 * xdiff), (2 * ydiff)), (int) (angle - adiff),
				(int) (adiff * 2));
		g.setColor(old);
	}

	private void drawSpeedModel(Graphics g, ObjectTrainingModel otm) {
		Color old = g.getColor();
		g.setColor(Color2.orangeRed);
		Point2f pos = otm.getPosition();
		// the other way round in soccerscope

		int speedMin = otm.getMin_speed();
		int speedMax = otm.getMax_speed();

		float angle = -otm.getSpeed_angle();
		float adiff = otm.getSpeed_angle_diff();

		// check, if an alignment exists
		if (otm instanceof PlayerTrainingModel) {
			PlayerTrainingModel ptm = (PlayerTrainingModel) otm;
			if (ptm.getAlignSpeedWithBody()) {
				angle = -ptm.getBody_angle();
				adiff = ptm.getBody_angle_diff();
			}
		}

		for (int speedAct = speedMin; speedAct <= speedMax; speedAct += 2) {

			float ydiff = 0.04f * speedAct;
			float xdiff = 0.04f * speedAct;

			// draw min:
			this.drawArc(g, new Point2f(pos.x - xdiff, pos.y - ydiff),
					new Tuple2f((2 * xdiff), (2 * ydiff)),
					(int) (angle - adiff), (int) (adiff * 2));
		}
		// Point2f p = otm.generateSpeed();
		// g.setColor(Color2.black);
		// this.fillOval(g, new Point2f(p.x - 1, p.y - 1),
		// new Tuple2f(2,(2)));
		g.setColor(old);
	}

}
